package com.yaolong.api.modules.gen.genengines;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.util.FileUtils;
import com.yaolong.api.modules.gen.genengines.CustomAbstractTemplateEngine;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.StringTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import com.yaolong.api.modules.gen.config.CustomConfigs;
import com.yaolong.api.modules.gen.config.CustomOutputTemplateResultConfig;
import com.yaolong.api.modules.gen.config.CustomTemplateConfig;
import com.yaolong.api.modules.gen.constants.FileGroupType;
import com.yaolong.api.modules.gen.constants.GenConstants;
import com.yaolong.api.modules.gen.utils.TemplateUtil;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * @author yaolong
 * @version V1.0.0
 * @program EasyCode
 * @description 自定义Freemarker引擎
 * @create 2022-12-29 09:37
 **/
public class CustomFreemarkerTemplateEngine extends CustomAbstractTemplateEngine {
    private Configuration configuration;


    @Override
    public CustomFreemarkerTemplateEngine init(@NotNull ConfigBuilder configBuilder) {
        this.configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        this.configuration.setDefaultEncoding(ConstVal.UTF8);
        initTemplateLoader(configBuilder);
        return this;
    }

    /**
     * <p>
     * 初始化模板加载器
     * </p>
     *
     * @return
     * @version 1.0.0 <br>
     * @date 2022/12/29 21:59 <br>
     * @author yaolonga <br>
     */
    private void initTemplateLoader(@NotNull ConfigBuilder configBuilder) {
        //创建字符串加载器并设置
        StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
        InjectionConfig injectionConfig = configBuilder.getInjectionConfig();
        if (!ObjectUtils.isEmpty(injectionConfig.getCustomMap())){
            Map<String, Object> customMap = injectionConfig.getCustomMap();
            CustomConfigs customConfigs = (CustomConfigs) customMap.get(GenConstants.CUSTOM_CONFIG_FIELD);
            CustomTemplateConfig customTemplateConfig = customConfigs.getCustomTemplateConfig();
            Map<String, String> stringTemplates = customTemplateConfig.getStringTemplates();
            stringTemplates.forEach(stringTemplateLoader::putTemplate);
        }
        //TODO FileLoader
        //类路径loader
        ClassTemplateLoader classTemplateLoader = new ClassTemplateLoader(CustomFreemarkerTemplateEngine.class, "/");
        //支持多个加载器
        MultiTemplateLoader multiTemplateLoader = new MultiTemplateLoader(new TemplateLoader[] {
                stringTemplateLoader,
                classTemplateLoader
        });
        this.configuration.setTemplateLoader(multiTemplateLoader);
    }


    @Override
    public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
        Template template = this.configuration.getTemplate(templatePath);
        FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, ConstVal.UTF8);
        try {
            template.process(objectMap, outputStreamWriter);
        } catch (Throwable var9) {
            try {
                fileOutputStream.close();
            } catch (Throwable var8) {
                var9.addSuppressed(var8);
            }
            throw var9;
        }
        fileOutputStream.close();
        //
    }

    @Override
    public String writer2String(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws IOException {
        Template template = this.configuration.getTemplate(templatePath);
        try {
           return setResultConfig(objectMap, outputFile, template);
        } catch (TemplateException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public @NotNull String templateFilePath(@NotNull String filePath) {
         return filePath + ".ftl";
    }

    /**
     * <p>
     * 设置生成结果配置 输出类型为string时生效
     * </p>
     * @version 1.0.0 <br>
     * @date 2022/12/30 0:22 <br>
     * @author yaolonga <br>
     * @param objectMap
 * @param outputFile
 * @param template
     * @return void
     */
    private String setResultConfig(@NotNull Map<String, Object> objectMap, @NotNull File outputFile, Template template) throws TemplateException, IOException {
        //字符串Writer用于返回
        StringWriter stringWriter = new StringWriter();
        template.process(objectMap, stringWriter);
        String filePath = outputFile.getAbsolutePath();
        String templateStr = stringWriter.toString();
        this.setResult(objectMap,  filePath, templateStr);
        return stringWriter.toString();
    }


}
